const catchAsync = require('../utils/catchAsync')
const AppError = require('../utils/appError')
const jwtUtil = require('../utils/jwtUtil')
const User = require('../models/user')
const client = require('../utils/redisClient')

/**
 * 拦截器middleware
 * @param {*} req
 * @param {*} res
 * @param {*} next
 */
module.exports = catchAsync(async (req, res, next) => {
  // 从请求头中获取token
  let token
  if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
    token = req.headers.authorization.split(' ')[1]
  }
  if (!token) return next(new AppError('你还没有登录，请先登录', 401))

  // 检查黑名单
  const isBlacklisted = await client.get(`blacklist:${token}`)
  if (isBlacklisted) return next(new AppError('Token 已失效，请重新登录', 401))

  // 检查登录状态
  const decoded = await jwtUtil.verifyToken(token)
  const redisToken = await client.get(`token:${decoded.id}`)
  if (!redisToken || redisToken !== token) {
    return next(new AppError('登录状态已过期，请重新登录', 401))
  }

  // 检查用户是否存在
  const freshUser = await User.findById(decoded.id)
  if (!freshUser) {
    return next(new AppError('该 token 的主人不存在🔨', 401))
  }

  // 一切没问题，放行
  // 顺便带上token和用户信息
  req.token = token
  req.user = freshUser
  next()
})
